from PIL import Image, ImageDraw, ImageFont
import string
import random
import io


class captcha:
    def __init__(self, width=200, height=75, font_size=55):
        """
        初始化验证码生成器。

        Args:
        - width (int): 图片宽度，默认为200像素。
        - height (int): 图片高度，默认为75像素。
        - font_size (int): 字体大小，默认为55像素。
        """
        self.width = width
        self.height = height
        self.font_size = font_size
        self.chars = string.ascii_letters + string.digits  # 验证码字符集合
        self.bgcolor = (255, 255, 255)  # 图片背景颜色
        self.linecolor = (random.randint(0, 128), random.randint(0, 128), random.randint(0, 128))  # 干扰线颜色
        self.dotcolor = (random.randint(0, 128), random.randint(0, 128), random.randint(0, 128))  # 干扰点颜色
        self.fontcolor = (random.randint(0, 128), random.randint(0, 128), random.randint(0, 128))  # 字体颜色

    def generate_captcha(self):
        """
        生成验证码图片和文本。

        Returns:
        - captcha_text (str): 生成的验证码文本。
        - image_bytes (bytes): 生成的验证码图片的二进制数据。
        """
        captcha_text = ''.join(random.choice(self.chars) for _ in range(4))  # 随机生成验证码文本
        image = Image.new('RGB', (self.width, self.height), self.bgcolor)  # 创建RGB模式的空白图片
        draw = ImageDraw.Draw(image)  # 创建可在图像上绘图的对象

        font = ImageFont.load_default().font_variant(size=self.font_size)  # 加载默认字体并调整大小

        # 绘制干扰线
        for i in range(5):
            x1 = random.randint(0, self.width)
            y1 = random.randint(0, self.height)
            x2 = random.randint(0, self.width)
            y2 = random.randint(0, self.height)
            draw.line((x1, y1, x2, y2), fill=self.linecolor, width=3)

        # 绘制干扰点
        for i in range(200):
            x = random.randint(0, self.width)
            y = random.randint(0, self.height)
            draw.point((x, y), fill=self.dotcolor)

        # 计算总文本宽度并调整起始位置使居中
        total_width = sum(font.getbbox(char)[2] for char in captcha_text) + 30  # 30 = 10px * 3间隔
        start_x = (self.width - total_width) // 2

        # 绘制验证码文字，包括阴影效果
        current_x = start_x
        for char in captcha_text:
            char_width = font.getbbox(char)[2]

            # 随机垂直偏移
            y_offset = random.randint(-5, 5)

            # 绘制阴影效果的文字
            shadow_offset = random.randint(0, 3)
            draw.text((current_x + shadow_offset, 5 + y_offset + shadow_offset),
                      char, font=font, fill=(0, 0, 0))

            # 绘制文字
            draw.text((current_x, 5 + y_offset), char, font=font, fill=self.fontcolor)

            # 固定10像素间距
            current_x += char_width + 10

        # 将图像保存到二进制流
        image_byte_arr = io.BytesIO()
        image.save(image_byte_arr, format='PNG')
        image_byte_arr = image_byte_arr.getvalue()

        return captcha_text, image_byte_arr